package com.inifitness.admin.core.system.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.inifitness.admin.core.system.converter.EventConvert;
import com.inifitness.admin.core.system.mapper.SysEventMapper;
import com.inifitness.admin.core.system.model.entity.SysEvent;
import com.inifitness.admin.core.system.model.form.EventForm;
import com.inifitness.admin.core.system.model.query.EventPageQuery;
import com.inifitness.admin.core.system.model.vo.EventPageVO;
import com.inifitness.admin.core.system.service.SysEventService;
import com.inifitness.common.model.Option;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

/**
 * 系统管理-事件信息服务实现类
 *
 * @author
 * @since 2024-05-31 13:45:02
 */

@Service
@RequiredArgsConstructor
@Log4j2
public class SysEventServiceImpl extends ServiceImpl<SysEventMapper, SysEvent> implements
    SysEventService {

  private final EventConvert eventConvert;
  private final ApplicationEventPublisher publisher;
  private final CacheManager cacheManager;

  @Override
  public Page<EventPageVO> getEventPage(EventPageQuery queryParams) {
    // 查询参数
    int pageNum = queryParams.getPageNum();
    int pageSize = queryParams.getPageSize();
    String keywords = queryParams.getKeywords();

    // 查询数据
    Page<SysEvent> page = this.page(
        new Page<>(pageNum, pageSize),
        new LambdaQueryWrapper<SysEvent>()
            .like(CharSequenceUtil.isNotBlank(keywords), SysEvent::getName, keywords)
            .select(
                SysEvent::getId,
                SysEvent::getName,
                SysEvent::getCode,
                SysEvent::getSort,
                SysEvent::getStatus,
                SysEvent::getUpdateTime,
                SysEvent::getDeleted,
                SysEvent::getCreateBy,
                SysEvent::getCreateTime,
                SysEvent::getUpdateBy
            )
    );

    return eventConvert.entity2Page(page);
  }

  @Override
  @Cacheable(cacheNames = "getEventForm", key = "#p0")
  public EventForm getEventForm(Long id) {
    // 获取entity
    SysEvent entity = this.getOne(new LambdaQueryWrapper<SysEvent>()
        .eq(SysEvent::getId, id)
        .select(
            SysEvent::getId,
            SysEvent::getName,
            SysEvent::getCode,
            SysEvent::getSort,
            SysEvent::getStatus,
            SysEvent::getUpdateTime,
            SysEvent::getDeleted,
            SysEvent::getCreateBy,
            SysEvent::getCreateTime,
            SysEvent::getUpdateBy
        ));
    Assert.isTrue(entity != null, "对象不存在");

    // 实体转换
    return eventConvert.entity2Form(entity);
  }

  @Override
  @CacheEvict(cacheNames = "listEventOptions", beforeInvocation = true)
  public boolean saveEvent(EventForm form) {
    boolean exist = this.count(new LambdaQueryWrapper<SysEvent>()
        .eq(SysEvent::getCode, form.getCode())) > 0;
    Assert.isTrue(!exist, "事件编码已存在");
    // 实体对象转换 form->entity
    SysEvent entity = eventConvert.form2Entity(form);
    // 持久化
    return this.save(entity);
  }

  @Override
  @Caching(
      put = {
          @CachePut(cacheNames = "listEventOptions"),
          @CachePut(cacheNames = "getEventForm", key = "#p0")
      }
  )
  public boolean updateEvent(Long id, EventForm form) {
    boolean exist = this.count(new LambdaQueryWrapper<SysEvent>()
        .eq(SysEvent::getCode, form.getCode())
        .ne(SysEvent::getId, id)) > 0;
    Assert.isTrue(!exist, "事件编码已存在");
    // 获取对象
    SysEvent entity = eventConvert.form2Entity(form);
    return this.updateById(entity);
  }

  @Override
  @CacheEvict(cacheNames = "listEventOptions")
  public boolean deleteEvents(String ids) {
    Assert.isTrue(CharSequenceUtil.isNotBlank(ids), "删除数据为空");
    List<String> idList = new ArrayList<>(Arrays.asList(ids.split(",")));
    //TODO:（2024-06-04 SJF ） 删除时，要注意事件是否已关联到消息模板一类的内容。同时，删除时要关联删除params等
    // 删除对象
    for (String id : idList) {
      Optional.ofNullable(cacheManager.getCache("getEventForm")).map(c -> c.evictIfPresent(id));
    }
    return this.removeByIds(idList);
  }


  /**
   * 获取下拉列表
   *
   * @return
   */
  @Override
  @Cacheable(cacheNames = "listEventOptions")
  public List<Option<Long>> listEventOptions() {
    // 数据库数据
    List<SysEvent> list = this.list(new LambdaQueryWrapper<SysEvent>()
        .select(SysEvent::getId, SysEvent::getName)
    );

    // 转换下拉数据
    return CollUtil.emptyIfNull(list)
        .stream()
        .map(item -> new Option<Long>(item.getId(), item.getName()))
        .toList();
  }
}
